<?php

/**
 * Form that adds elements that correspond to the table fields.
 *
 * @author     Mon Zafra <monzee at gmail>
 * @copyright  (c)2009 Mon Zafra
 * @category   Mz
 * @package    modules
 * @subpackage crud
 * @license    http://mz-project.googlecode.com/svn/trunk/LICENSE    MIT License
 * @version    SVN: $Id: Table.php 22 2009-05-08 17:08:41Z monzee $
 */
class Crud_Form_Table extends Zend_Form
{
    /**
     * @var Zend_Db_Table_Abstract
     */
    protected $_table;

    /**
     * constructor
     *
     * @param mixed|Zend_Db_Table_Abstract $table   Instance of the table or options
     *                                              to pass to Db_Table constructor or
     *                                              just the name of the table
     * @param array                        $options Options to pass to form constructor
     */
    public function __construct($table, $options=null) {
        if ($table instanceof Zend_Db_Table_Abstract) {
            $this->_table = $table;
        } elseif (is_array($table)) {
            $this->_table = new Crud_Model_Table($table);
        } else {
            $this->_table = new Crud_Model_Table( array(
                Zend_Db_Table_Abstract::NAME => $table) );
        }
        parent::__construct($options);
    }

    /**
     * Add elements
     *
     * @todo set decorators
     */
    public function init()
    {
        $inflector = new Crud_View_Helper_Inflect();

        $table = $this->_table;
        $meta = $table->info(Zend_Db_Table_Abstract::METADATA);

        $elemLi = array(
            'ViewHelper', 'Label', 'Errors',
            array('HtmlTag', array('tag' => 'li'))
        );
        $elemPlain = array('ViewHelper');
        $checkLi = array(
            'ViewHelper',
            array('Label', array('class' => 'checkbox', 'placement' => 'append')),
            'Errors',
            array('HtmlTag', array('tag' => 'li'))
        );
        $groupDecors = array('FormElements', array(
            'HtmlTag',
            array('tag' => 'li', 'class' => 'actions'))
        );
        $formDecors = array(
            'FormElements',
            array('HtmlTag', array('tag' => 'ul', 'class' => 'list-form')),
            'Form'
        );

        $this->setDisableLoadDefaultDecorators(true)
             ->setDecorators($formDecors);

        foreach ($meta as $col => $colData) {
            $type = $this->_getGeneralType($colData['DATA_TYPE']);
            $opts = array(
                'label' => $inflector->inflect($col)->toPhrase(Crud_View_Helper_Inflect::UC_FIRST),
                'value' => $colData['DEFAULT'],
                'class' => 'text',
                'decorators' => $elemLi
            );

            if (!$colData['NULLABLE']) {
                $opts['required'] = true;
            }
            // TODO: add alnum/int/real validators depending on the datatype
//            if ($maxLen = $colData['LENGTH'] && ($type == 'char' || $type == 'text')) {
//                $opts['validators'][] = array('StringLength', false, array(0, $maxLen));
//            }

            $chkOpts = $opts;
            $chkOpts['decorators'] = $checkLi;
            $chkOpts['class'] = 'checkbox';

            switch ($type) {
                case 'boolean':
                    $this->addElement('checkbox', $col, $chkOpts);
                    break;
                case 'char':
                case 'float':
                case 'int':
                case 'date':
                case 'datetime':
                    if (false !== strpos($col, 'password')) {
                        $this->addElement('password', $col, $opts);
                    } else {
                        $this->addElement('text', $col, $opts);
                    }
                    break;
                case 'text':
                    $this->addElement('textarea', $col, $opts);
                    break;
                default:
                    break;
            }

        }
        $this->addElement('submit', 'submit', array('label' => 'Commit changes',
                                                    'class' => 'button',
                                                    'ignore' => true,
                                                    'decorators' => $elemPlain))
             ->addElement('reset', 'reset', array('label' => 'Reset', 
                                                  'class' => 'button',
                                                  'ignore' => true,
                                                  'decorators' => $elemPlain))
             ->addDisplayGroup(array('submit', 'reset'), 'actions',
                 array('decorators' => $groupDecors));
    }

    protected function _getGeneralType($type)
    {
        $type = strtolower($type);
        if (false !== strpos($type, 'bool')) {
            return 'boolean';
        } else if (false !== strpos($type, 'int') || $type == 'numeric') {
            return 'int';
        } else if (in_array($type, array('float', 'real'))) {
            return 'float';
        } else if (false !== strpos($type, 'char')) {
            return 'char';
        } else if (false !== strpos($type, 'text')) {
            return 'text';
        }
        return $type;
    }

}
